package jee.demo.core;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.hsqldb.HsqldbUtils;
import jee.demo.pro.app.AppConfig;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.springframework.mock.web.*;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.servlet.*;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;


/**
 * JUnit测试action时使用的基类
 *
 * @author fule
 */
public class JUnitController {
    private static HandlerMapping handlerMapping;
    private static HandlerAdapter handlerAdapter;


    protected static MockServletContext servletContext;
    protected static MockServletConfig servletConfig;
    protected MockHttpServletRequest request;
    protected MockHttpServletResponse response;
    protected MockHttpSession session;
    protected MockPageContext pageContext;


    /**
     * 执行request请求的action
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @return ModelAndView
     * @throws Exception
     */
    public Object excuteAction(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 这里需要声明request的实际类型，否则会报错
        request.setAttribute(HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING, true);
        HandlerExecutionChain chain = handlerMapping.getHandler(request);
        ModelAndView model = null;
        try {
            model = handlerAdapter.handle(request, response, chain.getHandler());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return model;
    }

    @Before
    public void initServletMockObjects() {
        servletContext = new MockServletContext();
        response = new MockHttpServletResponse();
        request = new MockHttpServletRequest();
        session = new MockHttpSession();
        request.setSession(session);
        pageContext = new MockPageContext(servletContext, request, response);
    }

    /**
     * 测试开始前先启动数据库，再加载spring
     */
    @BeforeClass
    public static void setup() {
        // 启动hsql数据库
        HsqldbUtils.start(HsqldbUtils.class.getResource("/") + "database");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        if (handlerMapping == null) {
            String[] configs = {"file:src/main/config/spring*.xml"};
            XmlWebApplicationContext context = new XmlWebApplicationContext();
            context.setConfigLocations(configs);
            MockServletContext msc = new MockServletContext();
            context.setServletContext(msc);
            context.refresh();
            msc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,context);// TODO

            handlerMapping = context.getBean(RequestMappingHandlerMapping.class);
            handlerAdapter = (HandlerAdapter) context.getBean(context.getBeanNamesForType(RequestMappingHandlerAdapter.class)[0]);
        }

        AppConfig.init();
    }

    /**
     * 测试完成后关闭数据库
     * @throws Throwable
     */
    @AfterClass
    public static void destroy() throws Throwable {
        HsqldbUtils.shutdown();
    }
}
